package com.blogs.meachine;

import com.blogs.enums.TurnstileEvents;
import com.blogs.enums.TurnstileStates;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateMachinePersist;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.*;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.persist.StateMachinePersister;
import org.springframework.statemachine.support.DefaultStateMachineContext;

import java.util.EnumSet;

/**
 * @Author: xiaokai
 * @Description:
 * @Date: 2019/5/28
 * @Version: 1.0
 */
@Slf4j
@Configuration
@EnableStateMachineFactory
public class StatemachineConfigurer extends EnumStateMachineConfigurerAdapter<TurnstileStates, TurnstileEvents> {


    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Autowired
    private BizStateMachinePersist bizStateMachinePersist;

    @Bean
    public StateMachinePersister<TurnstileStates, TurnstileEvents, Integer> stateMachinePersist() {
        return new DefaultStateMachinePersister<>(bizStateMachinePersist);
    }


    /**
     * 设置初始化状态
     *
     * @param states
     * @throws Exception
     */
    @Override
    public void configure(StateMachineStateConfigurer<TurnstileStates, TurnstileEvents> states) throws Exception {

        states
                .withStates()
                //初始化当前状态为锁定
                .initial(TurnstileStates.Locked)
                .states(EnumSet.allOf(TurnstileStates.class));
        super.configure(states);
    }

    /**
     * 根据收到对的状态进行对应匹配
     *
     * @param transitions
     * @throws Exception
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<TurnstileStates, TurnstileEvents> transitions) throws Exception {
        transitions
                .withExternal()
                // 指定状态来源和目标
                .source(TurnstileStates.Unlocked).target(TurnstileStates.Locked)
                // 指定触发事件
                .event(TurnstileEvents.PUSH).action(customerPassAndLock())
                .and()
                .withExternal()
                .source(TurnstileStates.Locked).target(TurnstileStates.Unlocked)
                .event(TurnstileEvents.COIN).action(turnstileUnlock());
        super.configure(transitions);
    }


    @Override
    public void configure(StateMachineConfigurationConfigurer<TurnstileStates, TurnstileEvents> config) throws Exception {
        config
                .withConfiguration()
                // 指定状态机的处理监听器
                .listener(listener())
                .machineId("turnstileStateMachine");
        super.configure(config);
    }

    private StateMachineListener<TurnstileStates, TurnstileEvents> listener() {
        return null;
    }

    /**
     *
     * @return
     */
    private Action<TurnstileStates, TurnstileEvents> customerPassAndLock() {
        return stateContext -> System.out.println("当游客通过后，锁定旋转门");
    }

    /**
     *
     * @return
     */
    private Action<TurnstileStates, TurnstileEvents> turnstileUnlock() {
        return stateContext -> System.out.println("解锁旋转门，请当前游客通过");
    }


}
